﻿using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using DevComponents.DotNetBar;
using DevComponents.AdvTree;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.esriSystem;
using PlanningGIS.Win.Controls;
using PlanningGIS.ArcGIS;
using PlanningGIS.ArcGIS.Custom;
using PlanningGIS.Util.IO;
using PlanningGIS.Util.Log;

namespace PlanningGIS.Engine.Controls
{
    /// <summary>
    /// 数据对话框，用于打开或保存数据
    /// </summary>
    public abstract partial class FrmOpenData : Office2007Form
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public FrmOpenData()
        {
            InitializeComponent();
            fileList.FileDoubleClick += new DataFinished(this.fileList_FileDoubleClick);
            fileList.PathDoubleClick += new DataFinished(this.fileList_PathDoubleClick);
            fileList.FileSelected += new DataFinished(this.fileList_FileSelected);
        }

        /// <summary>
        /// 加载窗体
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmOpenData_Load(object sender, EventArgs e)
        { 
            this.Cursor = Cursors.WaitCursor;
            try
            {
                dirTree.Initialize();
                string p = System.IO.Path.GetDirectoryName(AoHelper._UserConfig);
                if (!Directory.Exists(p)) Directory.CreateDirectory(p);
                if (string.IsNullOrEmpty(InitialDirectory) || string.IsNullOrWhiteSpace(InitialDirectory))
                {
                    InitialDirectory = FileHelper.ReadIniValue("DataPath", KEY, "C:\\", AoHelper._UserConfig);
                }
                if (!string.IsNullOrWhiteSpace(InitialDirectory))
                {
                    InitialDirectory = InitialDirectory.Trim();
                    if (InitialDirectory.EndsWith("\\")) InitialDirectory = InitialDirectory.Substring(0, InitialDirectory.Length - 1);
                }
                txtDirName.Text = InitialDirectory;                
                fileList.SetCurrentDir(InitialDirectory, zjgisChangeType.DirName);
                dirTree.SetSelectPath(InitialDirectory);
                InitialDirectory = "";//用过之后清空，以免影响下一次初始化路径
            }
            catch (Exception ex)
            {
                LogHelper.WriteErrorText(ex);
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }

        #region 变量与属性

        /// <summary>
        /// sde连接名称
        /// </summary>
        public const string SDE_CONNECT = "连接到空间数据库";
               

        /// <summary>
        /// 注册表剑指
        /// </summary>
        private const string KEY = "OpenDataCurrentPath";

        /// <summary>
        /// 数据集集合对象
        /// </summary>
        private List<IDataset> _Datasets = null;

        /// <summary>
        /// 图层集合对象
        /// </summary>
        private List<ILayer> _LayerFiles = null;

        /// <summary>
        /// 确定按钮点击事件
        /// </summary>
        public EventHandler OnOkClick = null;

        /// <summary>
        /// CAD或DGN的预览图（因为一次只能选中一个预览图，所以不需要用集合）
        /// </summary>
        [Browsable(false)]
        public ICadDrawingDataset CadDrawingDataset { get; protected set; }

        /// <summary>
        /// 获取当前选择的路径
        /// </summary>
        [Browsable(false)]
        public string ParentName { get; protected set; }
        
        /// <summary>
        /// 获取（第一个）数据的完整路径
        /// </summary>
        [Browsable(false)]
        public string FullName
        {
            get
            {
                string s = "";
                if (txtDirName.Text.Trim().EndsWith("\\"))
                    s = txtDirName.Text.Trim() + txtFileName.Text.Trim().Split('|')[0];
                else
                    s = txtDirName.Text.Trim() + "\\" + txtFileName.Text.Trim().Split('|')[0];
                return s;
            }
        }

        /// <summary>
        /// 获取当前选择的名称
        /// </summary>
        [Browsable(false)]
        public string SelectName { get; protected set; }

        /// <summary>
        /// 获取当前选择的对象
        /// </summary>
        [Browsable(false)]
        public dynamic SelectObject { get; protected set; }

        /// <summary>
        /// 获取当前选择的工作空间
        /// </summary>
        [Browsable(false)]
        public IWorkspace SelectWorkspace
        {
            get
            {
                if (SelectObject == null || !(SelectObject is IDataNode)) return null;
                IDataNode nd = SelectObject as IDataNode;
                //if(nd.Workspace==null)
                //    nd.Open();
                return nd.Workspace;
            }
        }

        /// <summary>
        /// 设置多选
        /// </summary>
        public bool MultiSelect
        {
            get { return fileList.MultiSelect; }
            set { fileList.MultiSelect = value; }
        }
        
        /// <summary>
        /// 设置默认路径，若不设则取上一次打开数据的路径
        /// </summary>
        public string InitialDirectory { get; set; }

        /// <summary>
        /// 对话框显示的类型：打开或保存
        /// </summary>
        private zjgisDialogType _DialogType = zjgisDialogType.Open;
        /// <summary>
        /// 对话框显示的类型：打开或保存
        /// </summary>
        [Browsable(false)]
        protected zjgisDialogType DialogType
        {
            get { return _DialogType; }
            set
            {
                _DialogType = value;
                if (_DialogType == zjgisDialogType.Save)
                {
                    fileList.MultiSelect = false;
                    this.Text = "保存数据";
                }
                else
                {
                    this.Text = "打开数据";
                }
            }
        }
        
        /// <summary>
        /// 是否允许从命名
        /// </summary>
        public bool AllowReName
        {
            get { return txtFileName.Visible; }
            set
            {
                txtFileName.Visible = value;
                lblFileName.Visible = value;
            }
        }

        /// <summary>
        /// 是否缩放到图层
        /// </summary>
        public bool IsZoom
        {
            get { return chkZoom.Checked; }
            set { chkZoom.Checked = value; }
        }

        /// <summary>
        /// 获取或设置
        /// </summary>
        public zjgisOpenType OpenType { get; set; }
        #endregion

        #region 新建数据库操作
        /// <summary>
        /// 文件路径改变
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtDirName_TextChanged(object sender, EventArgs e)
        {
            mnuCreate.Enabled = false;
            if (string.IsNullOrWhiteSpace(txtDirName.Text) || string.IsNullOrEmpty(txtDirName.Text)) return;
            if (Directory.Exists(txtDirName.Text))
            {
                btnUp.Enabled = (txtDirName.Text.LastIndexOf("\\") > 1) ? true : false;
                if (!txtDirName.Text.ToLower().EndsWith(".gdb"))
                {
                    mnuCreate.Enabled = true;
                }
            }
        }

        /// <summary>
        /// 创建mdb
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCreateMDB_Click(object sender, EventArgs e)
        {
            FrmText frm = new FrmText()
            {
                Text = "创建MDB",
                ToolTip = "请输入数据库名称：",
                AllowNull = false
            };
            if (frm.ShowDialog(this) != System.Windows.Forms.DialogResult.OK) return;
            string p = txtDirName.Text + "\\" + frm.Value;
            if (!p.ToLower().EndsWith(".mdb")) p += ".mdb";
            if (File.Exists(p))
            {
                MsgHelper.ShowWarningMsgbox(this, "数据库名称已存在，请重新输入");
                return;
            }
            IWorkspace workspace = PlanningGIS.ArcGIS.WorkspaceHelper.CreateAccessWorkspace(p);
            if (workspace != null)
            {
                Marshal.FinalReleaseComObject(workspace);
                workspace = null;
                btnRefresh_Click(null, null);
            }
        }

        /// <summary>
        /// 创建GDB
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCreateGDB_Click(object sender, EventArgs e)
        {
            FrmText frm = new FrmText()
            {
                Text = "创建GDB",
                ToolTip = "请输入数据库名称：",
                AllowNull = false
            };
            if (frm.ShowDialog(this) != System.Windows.Forms.DialogResult.OK) return;
            string p = txtDirName.Text + "\\" + frm.Value;
            if (!p.ToLower().EndsWith(".gdb")) p += ".gdb";
            if (Directory.Exists(p))
            {
                MsgHelper.ShowWarningMsgbox(this, "数据库名称已存在，请重新输入");
                return;
            }
            IWorkspace workspace = PlanningGIS.ArcGIS.WorkspaceHelper.CreateGDBWorkspace(p);
            if (workspace != null)
            {
                Marshal.FinalReleaseComObject(workspace);
                workspace = null;
                btnRefresh_Click(null, null);
            }
        }

        /// <summary>
        /// 创建目录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCreateDir_Click(object sender, EventArgs e)
        {
            FrmText frm = new FrmText()
            {
                Text = "创建目录",
                ToolTip = "请输入目录名称：",
                AllowNull = false
            };
            if (frm.ShowDialog(this) != System.Windows.Forms.DialogResult.OK) return;
            if (string.IsNullOrEmpty(frm.Value) || string.IsNullOrWhiteSpace(frm.Value))
            {
                MsgHelper.ShowWarningMsgbox(this, "目录名称不能为空");
                return;
            }
            string p = txtDirName.Text + "\\" + frm.Value;
            if (Directory.Exists(p))
            {
                MsgHelper.ShowWarningMsgbox(this, "目录已存在，请重新输入");
                return;
            }
            Directory.CreateDirectory(p);
            btnRefresh_Click(null, null);
        }
        #endregion

        #region 操作
        
        /// <summary>
        /// 显示别名
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void chkAlias_CheckedChanged(object sender, EventArgs e)
        {
            fileList.RefreshName(chkAlias.Checked);
        }

        /// <summary>
        /// 目录点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dirTree_NodeClick(object sender, TreeNodeMouseEventArgs e)
        {
            SetSelectValue(e.Node);
        }

        /// <summary>
        /// 选择节点
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dirTree_AfterNodeSelect(object sender, DevComponents.AdvTree.AdvTreeNodeEventArgs e)
        {
            btnBack.Enabled = fileList.Canback();
            btnForward.Enabled = fileList.CanForward();            
            if (e.Node == null) return;
            btnUp.Enabled = (e.Node.Parent != null);
            SetSelectValue(e.Node);
            if (e.Action == eTreeAction.Code) return;            
            Cursor = Cursors.WaitCursor;
            fileList.SetCurrentDir(e.Node.Tag, zjgisChangeType.Dir);
            chkAlias.Checked = false;
            Cursor = Cursors.Default;
        }

        /// <summary>
        /// 设置选择的值
        /// </summary>
        /// <param name="node"></param>
        private void SetSelectValue(Node node)
        {
            if (node == null) return;
            txtFileName.Text = "";
            this.ParentName = node.Parent == null ? "我的电脑" : node.Parent.Name;
            this.SelectName = node.Text;
            //this.FullName = node.Name;
            txtDirName.Text = node.Name;
            if (node.Tag == null) return;
            SelectObject = node.Tag;
        }

        /// <summary>
        /// 选择文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fileList_FileSelected(object sender, DataEventArgs e)
        {
            if (e == null) return;
            if (e.Data is string)
            {
                txtFileName.Text = e.Data;
                if (fileList.SelectedItems.Count > 0)
                    SelectObject = fileList.SelectedItems[0].Tag;
                SetSelectValue(e.Data);
            }           
        }
        
        /// <summary>
        /// 双击文件列表项
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fileList_FileDoubleClick(object sender, DataEventArgs e)
        {
            if (e == null) return;
            if (fileList.SelectedItems.Count != 1) return;
            if (e.Data is IDataNode)
            {
                txtFileName.Text = e.Data.Name;
                if (fileList.SelectedItems.Count > 0)
                    SelectObject = fileList.SelectedItems[0].Tag;
                SetSelectValue(e.Data);
                btnOK_Click(null, null);
            }            
        }

        /// <summary>
        /// 设置选择的值
        /// </summary>
        private void SetSelectValue(dynamic data)
        {
            this.ParentName = txtDirName.Text.Trim();
            this.SelectName = txtFileName.Text.Trim();
            //if (txtDirName.Text.Trim().EndsWith("\\"))
            //    this.FullName = txtDirName.Text.Trim() + txtFileName.Text.Trim().Split('|')[0];
            //else
            //    this.FullName = txtDirName.Text.Trim() + "\\" + txtFileName.Text.Trim().Split('|')[0];
        }

        /// <summary>
        /// 双击目录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void fileList_PathDoubleClick(object sender, DataEventArgs e)
        {
            if (e == null) return;
            if (e.Data is string)
            {
                txtDirName.Text = e.Data;
                chkAlias.Checked = false;
                SelectObject = e.Data;
                dirTree.SetSelectPath(e.Data);
            }            
        }

        /// <summary>
        /// 改变目录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtFileName_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Return)
            {
                if (string.IsNullOrWhiteSpace(txtFileName.Text) || string.IsNullOrEmpty(txtFileName.Text))  return;
                if (!Directory.Exists(txtFileName.Text))
                {
                    return;
                }
                else
                {
                    Cursor = Cursors.WaitCursor;
                    fileList.SetCurrentDir(txtFileName.Text, zjgisChangeType.FileName);
                    dirTree.SetSelectPath(txtFileName.Text);
                    Cursor = Cursors.Default;
                    chkAlias.Checked = false;
                    txtFileName.Text = "";
                }
            }
        }

        /// <summary>
        /// 确定
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOK_Click(object sender, EventArgs e)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(this.ParentName)) return;
                if (string.IsNullOrWhiteSpace(this.SelectName)) return;
                FileHelper.WriteIniValue("DataPath", KEY, txtDirName.Text, AoHelper._UserConfig);
                if (_Datasets != null) _Datasets.Clear();
                if (OnOkClick != null) OnOkClick(null, null);
                else
                {
                    DialogResult = DialogResult.OK;
                    Close();
                }
            }
            catch (Exception ex)
            {
                MsgHelper.ShowInfomationMsgbox("加载数据失败！");
                LogHelper.WriteErrorText("加载数据失败:" + ex.Message);
            }
            
        }

        #endregion
        
        #region  上一步下一步操作类
        /// <summary>
        /// 返回
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnBack_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            fileList.Backward();
            this.Cursor = Cursors.Default;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnForward_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            fileList.Forward();
            this.Cursor = Cursors.Default;
        }

        /// <summary>
        /// 向上
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnUp_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            try
            {
                if (dirTree.SelectedNode != null && dirTree.SelectedNode.Parent != null)
                {
                    dirTree.SelectedNode = dirTree.SelectedNode.Parent;
                    fileList.SetCurrentDir(dirTree.SelectedNode.Tag, zjgisChangeType.Dir);
                }
                else if (!string.IsNullOrWhiteSpace(txtDirName.Text))
                {
                    string tmp = txtDirName.Text.Trim();
                    if (tmp.EndsWith("\\")) tmp = tmp.Substring(0, tmp.Length - 1);
                    int idx = tmp.LastIndexOf("\\");
                    string path = tmp.Substring(0, idx);
                    txtDirName.Text = path;
                    fileList.SetCurrentDir(path, zjgisChangeType.Dir);
                }
            }
            catch
            {
                
            }            
            this.Cursor = Cursors.Default;
        }

        /// <summary>
        /// 刷新目录
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRefresh_Click(object sender, EventArgs e)
        {
            this.dirTree.UpdateNode();
            this.fileList.SetCurrentDir(this.dirTree.SelectedNode.Tag);
        }
        #endregion
        
        #region 获取DataNode和IDataset集合

        /// <summary>
        /// 获取所有选择的数据集或数据要素对象
        /// </summary>
        /// <returns></returns>
        public List<IDataset> GetAllDatasets()
        {
            CadDrawingDataset = null;
            _LayerFiles = null;
            List<IDataset> datasets = new List<IDataset>();
            List<IDataNode> nodes = fileList.GetAllNodes<IDataNode>();
            if (nodes == null || nodes.Count == 0) return datasets;
            foreach (IDataNode itmNode in nodes)
            {
                try
                {
                    if (itmNode is CadDrawingDatasetNode)
                    {
                        CadDrawingDatasetNode cadDrawingDatasetNode = itmNode as CadDrawingDatasetNode;
                        CadDrawingDataset = cadDrawingDatasetNode.OpenAsCadDrawingDatasetNode();
                    }
                    else if (itmNode is LayerNode)
                    {
                        if (_LayerFiles == null) _LayerFiles = new List<ILayer>();
                        LayerNode layerNode = itmNode as LayerNode;
                        ILayer lyr = layerNode.OpenLayer();
                        _LayerFiles.Add(lyr);
                    }
                    else
                    {
                        IDataset ds;
                        if (itmNode.Tag != null && itmNode.Tag is IDataset)
                            ds = itmNode.Tag as IDataset;
                        else
                            ds = itmNode.Open();
                        if (ds != null) datasets.Add(ds);
                    }
                }
                catch
                {
                }
            }
            return datasets;
        }

        /// <summary>
        /// 获取所有选择的节点
        /// </summary>
        /// <typeparam name="T">需要获取的节点类型，如IDataNode，LayerNode等</typeparam>
        /// <returns></returns>
        public List<T> GetSelectNode<T>()
        {            
            List<T> sel= fileList.GetSelectNode<T>();
            if(sel==null || sel.Count==0)
            {
                Node nd = dirTree.SelectedNode;
                if (nd.Tag != null && nd.Tag is IDataNode)
                {
                    IDataNode dnd = nd.Tag as IDataNode;
                    if (dnd is T)
                    {
                        sel = new List<T>();
                        sel.Add((T)dnd);
                    }
                    return sel;
                }
            }
            return sel;
        }

        /// <summary>
        /// 获取选择的数据
        /// </summary>
        /// <returns></returns>
        public List<IDataset> GetSelectDatasets()
        {
            CadDrawingDataset = null;
            _LayerFiles = null;
            List<IDataset> datasets = new List<IDataset>();
            List<IDataNode> nodes = fileList.GetSelectNode<IDataNode>();
            if (nodes == null || nodes.Count == 0) return datasets;
            foreach (IDataNode itmNode in nodes)
            {
                try
                {
                    if (itmNode is CadDrawingDatasetNode)
                    {
                        CadDrawingDatasetNode cadDrawingDatasetNode = itmNode as CadDrawingDatasetNode;
                        CadDrawingDataset = cadDrawingDatasetNode.OpenAsCadDrawingDatasetNode();
                    }
                    else if (itmNode is LayerNode)
                    {
                        if (_LayerFiles == null) _LayerFiles = new List<ILayer>();
                        LayerNode layerNode = itmNode as LayerNode;
                        ILayer lyr = layerNode.OpenLayer();
                        _LayerFiles.Add(lyr);
                    }
                    else
                    {
                        IDataset ds;
                        if (itmNode.Tag != null && itmNode.Tag is IDataset)
                            ds = itmNode.Tag as IDataset;
                        else
                            ds = itmNode.Open();
                        if (ds != null) datasets.Add(ds);
                    }
                }
                catch
                {
                }
            }
            return datasets;
        }
       
        /// <summary>
        /// 获取所有的栅格数据图层对象
        /// </summary>
        /// <returns></returns>
        public List<ILayer> GetRasterDatasetLyrs()
        {
            List<ILayer> pLayers = new List<ILayer>();
            if (_Datasets == null || _Datasets.Count == 0) _Datasets = GetAllDatasets();
            foreach (IDataset pDataset in _Datasets)
            {
                if (pDataset == null) continue;
                if (pDataset.Type == esriDatasetType.esriDTRasterDataset)
                {
                    IRasterLayer pRasterLayer = new RasterLayer();
                    pRasterLayer.CreateFromDataset(pDataset as IRasterDataset);
                    pLayers.Add(pRasterLayer);
                }
            }
            return pLayers;
        }

        /// <summary>
        /// 获取指定类型的所有选择的图层
        /// </summary>
        /// <param name="point2poly">true:点到面；false：面到点</param>
        /// <returns></returns>
        public List<ILayer> GetSelectLayers(bool point2poly = true)
        {
            List<IDataNode> selnodes = GetSelectNode<IDataNode>();
            if (selnodes == null || selnodes.Count == 0) return null;
            List<ILayer> layers = new List<ILayer>();
            foreach (IDataNode node in selnodes)
            {
                ILayer lyr = node.OpenLayer();
                if (lyr == null) continue;
                layers.Add(lyr);
            }
            layers.Sort2(point2poly);
            return layers;
        }

        /// <summary>
        /// 获取选择的数据表
        /// </summary>
        /// <returns></returns>
        public List<TableNode> GetTables()
        {
            return fileList.GetSelectNode<TableNode>();
        }

        #endregion
        
        /// <summary>
        /// 取消，关闭窗体
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        
        /// <summary>
        /// 对话框类型
        /// </summary>
        public enum zjgisDialogType
        {
            /// <summary>
            /// 打开文件
            /// </summary>
            Open,
            /// <summary>
            /// 保存文件
            /// </summary>
            Save
        }

    }

    /// <summary>
    /// 打开的类型
    /// </summary>
    public enum zjgisOpenType
    {
        /// <summary>
        /// 不指定类型
        /// </summary>
        Null = 0,

        /// <summary>
        /// 数据库
        /// </summary>
        Database = 1,

        /// <summary>
        /// 数据集
        /// </summary>
        Dataset = 2,

        /// <summary>
        /// 要素类
        /// </summary>
        FeatureClass = 4,

        /// <summary>
        /// 数据表
        /// </summary>
        Table = 8,

        /// <summary>
        /// 所有的类型
        /// </summary>
        All = 255
    }
   
}